#ifndef ELEC_AS_PLAYLIST_HH
#define ELEC_AS_PLAYLIST_HH

#include <iostream>
#include <list>
#include <string>

/* DESCRIPTION:
 * ------------
 * A structure that represents one track. Each track has a name, artist and
 * a length.
 */
typedef struct Track_s {
    std::string name;
    std::string artist;
    size_t length;
} Track;


/* DESCRIPTION:
 * ------------
 * The function reads the data of a new track from the parameter input stream,
 * creates a new Track and appends it to the parameter playlist (the new track
 * is added as the last track in the playlist).
 *
 * The data is in the input stream in the following format:
 *
 * <Track name>
 * <Track artist>
 * <Track length>
 *
 * Each piece of information is on its own line. You do not need to handle any
 * malformed input.
 *
 * PARAMETERS:
 * ------------
 * std::list<Track>& playlist: the playlist where the new track is added.
 * std::istream& is: the input stream.
 *
 * RETURNS:
 * ------------
 * Nothing.
 */
void addTrack(std::list<Track>& playlist, std::istream& is);


/* DESCRIPTION:
 * ------------
 * The function removes the parameter track from the playlist. If there is
 * no matching track in the playlist the function does nothing.
 *
 * If there are multiple instances of the same track, only the first found
 * track (from the beginning) is removed from the playlist.
 *
 * Two tracks are equal if all of their individual fields are equal, that is
 * they have the same name, artist and length.
 *
 * PARAMETERS:
 * ------------
 * std::list<Track>& playlist: the playlist where to remove the track from.
 * const Track& track: the track to be removed from the playlist.
 *
 * RETURNS:
 * ------------
 * Nothing.
 */
void removeTrack(std::list<Track>& playlist, const Track& track);


/* DESCRIPTION:
 * ------------
 * The function prints the playlist into the parameter output stream.
 *
 * Each track is printed on their own line in the following format:
 *
 * <Track name> - <Track artist> - <Track length> sec
 *
 * For example:
 *
 * All I Can See - Eva & Manu - 340 sec
 * Moar Ghosts 'n' Stuff - Deadmau5 - 300 sec
 *
 * PARAMETERS:
 * ------------
 * const std::list<Track>& playlist: the playlist to be printed.
 * std::ostream& os: the output stream where to print.
 *
 * RETURNS:
 * ------------
 * Nothing.
 */
void printPlaylist(const std::list<Track>& playlist, std::ostream& os);


/* DESCRIPTION:
 * ------------
 * The function serves as a comparator when ordering tracks primarily by their
 * name.
 *
 * The function returns true if the track given as the first parameter is
 * "smaller", in other words, comes before the second parameter.
 *
 * As there can exist tracks with the same name, the function first compares the
 * tracks by their names, if the names are equal the function further compares
 * the artists. If even the artists are equal the function compares the lengths.
 *
 * This function should be usable with the sortPlaylist function to fully order
 * a playlist, primarily by the track names, in an ascending order.
 *
 * PARAMETERS:
 * ------------
 * const Track& l: the first parameter track.
 * const Track& r: the second parameter track.
 *
 * RETURNS:
 * ------------
 * True if the first parameter track is considered "smaller" than the second
 * parameter track.
 */

bool sortingPredicate(const Track& l, const Track& r);


/* DESCRIPTION:
 * ------------
 * The function sorts the parameter playlist using the parameter predicate.
 *
 * PARAMETERS:
 * ------------
 * std::list<Track>& playlist: the playlist to be sorted.
 *
 * bool (*predicate)(const Track&, const Track&): the predicate used to sort
 * the playlist.
 *
 * RETURNS:
 * ------------
 * Nothing.
 */
void sortPlaylist(std::list<Track>& playlist, bool (*predicate)(const Track& l, const Track& r));


/* DESCRIPTION:
 * ------------
 * The function merges the two parameter playlists, so that there are no
 * duplicates in the new merged playlist.
 *
 * After merging the tracks should be ordered by their name (hint: use the two
 * functions you wrote earlier).
 *
 * PARAMETERS:
 * ------------
 * const std::list<Track>& l: a playlist used in the merging.
 * const std::list<Track>& r: a playlist used in the merging.
 *
 * RETURNS:
 * ------------
 * The new merged playlist.
 */
std::list<Track> mergeWithoutDuplicates(const std::list<Track>& l, const std::list<Track>& r);

#endif
